// Fill out your copyright notice in the Description page of Project Settings.


#include "CreateMeshActor.h"
#include <StaticMeshAttributes.h>
#include <MeshDescriptionBuilder.h>

ACreateMeshActor::ACreateMeshActor()
{
 	PrimaryActorTick.bCanEverTick = true;

	_mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	SetRootComponent(_mesh);

	_mesh->SetStaticMesh(CreateMeshData());
	_mesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));

	static ConstructorHelpers::FObjectFinder<UMaterial> mtlAsset(
		TEXT("Material'/Game/BasicTexture.BasicTexture'"));
	if (mtlAsset.Succeeded())
	{
		UMaterialInstanceDynamic* mtl = UMaterialInstanceDynamic::Create(
			mtlAsset.Object, NULL);
		ChangeTexture(mtl);
		_mesh->SetMaterial(0, mtl);
	}
}

void ACreateMeshActor::BeginPlay()
{
	Super::BeginPlay();
}

void ACreateMeshActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

UStaticMesh* ACreateMeshActor::CreateMeshData()
{
	UStaticMesh* staticMesh = NewObject<UStaticMesh>(this, "UserMesh");
	FMeshDescription meshDesc;
	FStaticMeshAttributes attributes(meshDesc);
	attributes.Register();

	{
		FMeshDescriptionBuilder meshDescBuilder;
		meshDescBuilder.SetMeshDescription(&meshDesc);
		meshDescBuilder.EnablePolyGroups();
		meshDescBuilder.SetNumUVLayers(1);

		TArray<FVertexID> vertexIDs;
		vertexIDs.SetNum(8);
		vertexIDs[0] = meshDescBuilder.AppendVertex(FVector(0.0, 0.0, 0.0));
		vertexIDs[1] = meshDescBuilder.AppendVertex(FVector(100.0, 0.0, 0.0));
		vertexIDs[2] = meshDescBuilder.AppendVertex(FVector(100.0, 100.0, 0.0));
		vertexIDs[3] = meshDescBuilder.AppendVertex(FVector(0.0, 100.0, 0.0));
		vertexIDs[4] = meshDescBuilder.AppendVertex(FVector(0.0, 0.0, 100.0));
		vertexIDs[5] = meshDescBuilder.AppendVertex(FVector(100.0, 0.0, 100.0));
		vertexIDs[6] = meshDescBuilder.AppendVertex(FVector(100.0, 100.0, 100.0));
		vertexIDs[7] = meshDescBuilder.AppendVertex(FVector(0.0, 100.0, 100.0));

		GlobalData globalData;
		globalData.builder = &meshDescBuilder;
		globalData.vertexIDs = vertexIDs;
		globalData.polygonGroup = meshDescBuilder.AppendPolygonGroup();

		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(0, 0, -1), FVector2D(0, 0) },
			TriangleVertex{ 1, FVector(0, 0, -1), FVector2D(1, 0) },
			TriangleVertex{ 2, FVector(0, 0, -1), FVector2D(1, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(0, 0, -1), FVector2D(0, 0) },
			TriangleVertex{ 2, FVector(0, 0, -1), FVector2D(1, 1) },
			TriangleVertex{ 3, FVector(0, 0, -1), FVector2D(0, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(0, -1, 0), FVector2D(0, 0) },
			TriangleVertex{ 5, FVector(0, -1, 0), FVector2D(1, 1) },
			TriangleVertex{ 1, FVector(0, -1, 0), FVector2D(1, 0) });
		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(0, -1, 0), FVector2D(0, 0) },
			TriangleVertex{ 4, FVector(0, -1, 0), FVector2D(0, 1) },
			TriangleVertex{ 5, FVector(0, -1, 0), FVector2D(1, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 2, FVector(0, 1, 0), FVector2D(0, 0) },
			TriangleVertex{ 7, FVector(0, 1, 0), FVector2D(1, 1) },
			TriangleVertex{ 3, FVector(0, 1, 0), FVector2D(1, 0) });
		AddTriangleData(globalData,
			TriangleVertex{ 2, FVector(0, 1, 0), FVector2D(0, 0) },
			TriangleVertex{ 6, FVector(0, 1, 0), FVector2D(0, 1) },
			TriangleVertex{ 7, FVector(0, 1, 0), FVector2D(1, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 4, FVector(0, 0, 1), FVector2D(0, 0) },
			TriangleVertex{ 6, FVector(0, 0, 1), FVector2D(1, 1) },
			TriangleVertex{ 5, FVector(0, 0, 1), FVector2D(1, 0) });
		AddTriangleData(globalData,
			TriangleVertex{ 4, FVector(0, 0, 1), FVector2D(0, 0) },
			TriangleVertex{ 7, FVector(0, 0, 1), FVector2D(0, 1) },
			TriangleVertex{ 6, FVector(0, 0, 1), FVector2D(1, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(-1, 0, 0), FVector2D(0, 0) },
			TriangleVertex{ 3, FVector(-1, 0, 0), FVector2D(1, 0) },
			TriangleVertex{ 7, FVector(-1, 0, 0), FVector2D(1, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 0, FVector(-1, 0, 0), FVector2D(0, 0) },
			TriangleVertex{ 7, FVector(-1, 0, 0), FVector2D(1, 1) },
			TriangleVertex{ 4, FVector(-1, 0, 0), FVector2D(0, 1) });
		AddTriangleData(globalData,
			TriangleVertex{ 1, FVector(1, 0, 0), FVector2D(0, 0) },
			TriangleVertex{ 6, FVector(1, 0, 0), FVector2D(1, 1) },
			TriangleVertex{ 2, FVector(1, 0, 0), FVector2D(1, 0) });
		AddTriangleData(globalData,
			TriangleVertex{ 1, FVector(1, 0, 0), FVector2D(0, 0) },
			TriangleVertex{ 5, FVector(1, 0, 0), FVector2D(0, 1) },
			TriangleVertex{ 6, FVector(1, 0, 0), FVector2D(1, 1) });

		UStaticMesh::FBuildMeshDescriptionsParams builderParams;
		builderParams.bBuildSimpleCollision = true;
		builderParams.bFastBuild = true;

		TArray<const FMeshDescription*> meshDescList;
		meshDescList.Emplace(&meshDesc);
		staticMesh->BuildFromMeshDescriptions(meshDescList, builderParams);
	}
	return staticMesh;
}

void ACreateMeshActor::ChangeTexture(UMaterialInstanceDynamic* mtl)
{
	/*TArray<UTexture*> textures; TArray<FName> names;
	mtl->GetTexturesInPropertyChain(
		EMaterialProperty::MP_BaseColor, textures,
		&names, NULL);
	for (FName n : names)
		UE_LOG(LogTemp, Warning, TEXT("Param %s"), *n.ToString());*/

	static ConstructorHelpers::FObjectFinder<UTexture2D> texAsset(
		TEXT("Texture2D'/Game/StarterContent/Textures/T_Ceramic_Tile_M.T_Ceramic_Tile_M'"));
	if (texAsset.Succeeded())
		mtl->SetTextureParameterValue("BaseTexture", texAsset.Object);
}

void ACreateMeshActor::AddTriangleData(GlobalData& globalData, const TriangleVertex& v1,
	                                   const TriangleVertex& v2, const TriangleVertex& v3)
{
	FVertexInstanceID i1 = globalData.builder->AppendInstance(globalData.vertexIDs[v1.vertexIndex]);
	globalData.builder->SetInstanceNormal(i1, v1.instanceNormal);
	globalData.builder->SetInstanceUV(i1, v1.instanceUV, 0);
	globalData.builder->SetInstanceColor(i1, FVector4f(1.0f, 1.0f, 1.0f, 1.0f));

	FVertexInstanceID i2 = globalData.builder->AppendInstance(globalData.vertexIDs[v2.vertexIndex]);
	globalData.builder->SetInstanceNormal(i2, v2.instanceNormal);
	globalData.builder->SetInstanceUV(i2, v2.instanceUV, 0);
	globalData.builder->SetInstanceColor(i2, FVector4f(1.0f, 1.0f, 1.0f, 1.0f));

	FVertexInstanceID i3 = globalData.builder->AppendInstance(globalData.vertexIDs[v3.vertexIndex]);
	globalData.builder->SetInstanceNormal(i3, v3.instanceNormal);
	globalData.builder->SetInstanceUV(i3, v3.instanceUV, 0);
	globalData.builder->SetInstanceColor(i3, FVector4f(1.0f, 1.0f, 1.0f, 1.0f));

	globalData.builder->AppendTriangle(i1, i2, i3, globalData.polygonGroup);
}
